package com.medical.data.utils;

import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson2.JSONArray;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 日期工具类
 */
public class DateUtil {
    /**
     * 获取yyyyMMdd格式的数据
     */
    public final static String yyyyMMdd = "yyyyMMdd";

    /**
     * 获取yyyyMM格式的数据
     */
    public final static String yyyyMM = "yyyyMM";
    /**
     * 获取MMdd格式的数据
     */
    public final static String MMdd = "MMdd";
    /**
     * HH:mm格式的数据
     */
    public final static String HH_MM = "HH:mm";
    /**
     * 获取yyyyMMdd HH:mm:ss格式的数据
     */
    public final static String yyyyMMddHHmmss = "yyyyMMddHHmmss";

    /**
     * 获取yyyyMMdd HH:mm:ss格式的数据
     */
    public final static String yyyyMMdd_HHmmss = "yyyy-MM-dd HH:mm:ss";

    /**
     * 获取yyyy-MM-dd格式的数据
     */
    public final static String yyyy_MM_dd = "yyyy-MM-dd";
    /**
     * 获取yyyy/MM/dd格式的数据
     */
    public final static String yyyyFMMFdd = "yyyy/MM/dd";

    /**
     * 春天;
     */
    public static final Integer SPRING = 1;

    /**
     * 夏天;
     */
    public static final Integer SUMMER = 2;

    /**
     * 秋天;
     */
    public static final Integer AUTUMN = 3;

    /**
     * 冬天;
     */
    public static final Integer WINTER = 4;

    /**
     * 星期日;
     */
    public static final String SUNDAY = "星期日";

    /**
     * 星期一;
     */
    public static final String MONDAY = "星期一";

    /**
     * 星期二;
     */
    public static final String TUESDAY = "星期二";

    /**
     * 星期三;
     */
    public static final String WEDNESDAY = "星期三";

    /**
     * 星期四;
     */
    public static final String THURSDAY = "星期四";

    /**
     * 星期五;
     */
    public static final String FRIDAY = "星期五";

    /**
     * 星期六;
     */
    public static final String SATURDAY = "星期六";

    /**
     * 年
     */
    private static final String YEAR = "year";

    /**
     * 月
     */
    private static final String MONTH = "month";

    /**
     * 周
     */
    private static final String WEEK = "week";

    /**
     * 日
     */
    private static final String DAY = "day";

    /**
     * 时
     */
    private static final String HOUR = "hour";

    /**
     * 分
     */
    private static final String MINUTE = "minute";

    /**
     * 秒
     */
    private static final String SECOND = "second";

    public static final String DATE_TIME_FORMAT1 = "yyyy-MM-dd 00:00:00";
    public static final String DATE_TIME_FORMAT2 = "yyyy-MM-dd 23:59:59";
    /**
     * 锁对象
     */
    public final static Object LOCK_OBJECT = new Object();
    /**
     * 存放不同的日期模板格式的dataThreadMap的Map
     */
    public static Map<String,ThreadLocal<SimpleDateFormat>> dataThreadMap = new HashMap<>();

    /**
     * 返回一个ThreadLocal的dataThreadMap，每次只能new一次
     * @param format
     * @return
     */
    private static SimpleDateFormat getSdf(String format){
        ThreadLocal<SimpleDateFormat> formatThreadLocal = dataThreadMap.get(format);
        if (formatThreadLocal==null){
            synchronized (LOCK_OBJECT){
                formatThreadLocal = dataThreadMap.get(format);
                if (formatThreadLocal == null){
                    formatThreadLocal = ThreadLocal.withInitial(()->new SimpleDateFormat(format));
                    dataThreadMap.put(format,formatThreadLocal);
                }
            }
        }
        return formatThreadLocal.get();
    }

    /**
     * 获取一周日期
     * @param deviationWeek:偏移量：负数表示前面周，0表示当前周，正数表示未来周
     * @return
     */
    public static JSONArray getWeekDays(Integer deviationWeek){
        JSONArray jsonArray = new JSONArray();
        Calendar calendar = Calendar.getInstance();//当前日历
        calendar.add(Calendar.DAY_OF_MONTH,7*deviationWeek); //偏移，给指定的日期添加/减少时间,使用日表示
        for (int i = 0; i < 7; i++) {
            String date = getYyyyMMdd(calendar.getTime());
            jsonArray.add(date);
            //当前的偏移
            calendar.add(Calendar.DAY_OF_MONTH,1);//偏移一天
        }
        return jsonArray;
    }

    /**
     * 获取YyyyMMdd的日期
     * @param date
     * @return
     */
    public static String getYyyyMMdd(Date date){
        return getSdf(DateUtil.yyyyMMdd).format(date);
    }

    /**
     * Yyyy_MM_dd格式的日期
     * @return
     */
    public static String getYyyy_MM_dd(Date date){
        return getSdf(DateUtil.yyyy_MM_dd).format(date);
    }

    /**
     * Yyyy_MM_dd格式的日期
     * @return
     */
    public static String getFormatDate(Date date,String format){
        return getSdf(format).format(date);
    }

    /**
     * 获取今天的日期以Yyyy_MM_dd格式返回
     * @param
     */
    public static String getYyyy_MM_ddByToday(){
        return getYyyy_MM_dd(Calendar.getInstance().getTime());
    }

    /**
     * 判断某一个日期是否在某个时间段内
     * @param startTime
     * @param endTime
     * @param isTime
     * @return
     */
    public static Boolean isDateIn(Date startTime,Date endTime,Date isTime){
        if (isTime.before(startTime)||isTime.after(endTime)){
            return false;
        }
        return true;
    }
    /**
     * 判断两个日期时间大小，时间1大于等于时间2，则返回true
     */
    public static Boolean compareDateAndTime(Date time1, Date time2) {
        try {
            if (time1!=null && time2!=null && time1.getTime() >= time2.getTime()) {
                return true;
            }
        } catch (Exception e) {
           return false;
        }
        return false;
    }

    /**
     * 获取月的第一天
     * @param deviationMonth：偏移量
     * @return
     */
    public static Date getFirstDayOfMouth(Integer deviationMonth){
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH,deviationMonth); //设置月
        calendar.set(Calendar.DATE,1);//当月第一天
        SimpleDateFormat sdf = getSdf(DateUtil.DATE_TIME_FORMAT1);
        String date = sdf.format(calendar.getTime());
        Date parse = null;
        try {
            parse = sdf.parse(date);
        } catch (ParseException e) {
            return null;
        }
        return parse;
    }

    /**
     * 获取月的最后一天
     * @param deviationMonth
     * @return
     */
    public static String getLastDayOfMouth(Integer deviationMonth){
        if (deviationMonth == null)
            return null;
        deviationMonth = deviationMonth+1;
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH,deviationMonth); //设置月
        calendar.set(Calendar.DATE,0);//当月最后一天
        SimpleDateFormat sdf = getSdf(DateUtil.DATE_TIME_FORMAT2);
        String date = sdf.format(calendar.getTime());
        Date parse = null;
        try {
            parse = sdf.parse(date);
        } catch (ParseException e) {
            return null;
        }
        return date;
    }

    /**
     * 获取年的第一天
     * @param deviationYear
     * @return
     */
    public static Date getFirstDayOfYear(Integer deviationYear){
        if (deviationYear == null)
            return null;
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR,deviationYear); //设置年
        calendar.set(Calendar.MONTH,0);//当月第一月
        calendar.set(Calendar.DATE,1);//当月第一天
        SimpleDateFormat sdf = getSdf(DateUtil.DATE_TIME_FORMAT1);
        String date = sdf.format(calendar.getTime());
        Date parse = null;
        try {
            parse = sdf.parse(date);
        } catch (ParseException e) {
            return null;
        }
        return parse;
    }

    /**
     * 获取今天开始时间
     * @return
     */
    public static Date getBeginOfDay(Date date1){
        DateTime dateTime = cn.hutool.core.date.DateUtil.beginOfDay(date1);
        SimpleDateFormat sdf = getSdf(DateUtil.DATE_TIME_FORMAT1);
        String date = sdf.format(dateTime);
        DateTime parse = cn.hutool.core.date.DateUtil.parse(date);
        return parse;
    }

    /**
     * 获取今天结束时间
     * @return
     */
    public static Date getEndOfDay(Date date1){
        DateTime dateTime = cn.hutool.core.date.DateUtil.endOfDay(date1);
        SimpleDateFormat sdf = getSdf(DateUtil.DATE_TIME_FORMAT2);
        String date = sdf.format(dateTime);
        DateTime parse = cn.hutool.core.date.DateUtil.parse(date);
        return parse;
    }


    /**
     * 获取年的最后一天
     * @param deviationYear
     * @return
     */
    public static Date getLastDayOfYear(Integer deviationYear){
        if (deviationYear == null)
            return null;
        deviationYear = deviationYear + 1;
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR,deviationYear); //设置年
        calendar.set(Calendar.MONTH,0);//当月第一月
        calendar.set(Calendar.DATE,0);//上一个的最后一天
        SimpleDateFormat sdf = getSdf(DateUtil.DATE_TIME_FORMAT2);
        String date = sdf.format(calendar.getTime());
        Date parse = null;
        try {
            parse = sdf.parse(date);
        } catch (ParseException e) {
            return null;
        }
        return parse;
    }

    /**
     * 判断该日期是否为今天
     * @param time
     * @return
     */
    public static Boolean isToday(Date time){
        return getYyyy_MM_ddByToday().equals(getYyyy_MM_dd(time));
    }

    /**
     * 获取指定日期偏移天数
     * @param date
     * @param day
     * @return
     */
    public static Date offsetDay(Date date , int day){
        Calendar calendar = Calendar.getInstance();
        if (date != null){
            calendar.setTime(date);
        }
        calendar.add(Calendar.DATE,day);
        return calendar.getTime();
    }
    /**
     * 获取指定日期偏移月
     * @param date
     * @param mouth
     * @return
     */
    public static Date offsetMonth(Date date , int mouth){
        Calendar calendar = Calendar.getInstance();
        if (date != null){
            calendar.setTime(date);
        }
        calendar.add(Calendar.MONTH,mouth);
        return calendar.getTime();
    }
    /**
     * 获取指定日期偏移年
     * @param date
     * @param year
     * @return
     */
    public static Date offsetYear(Date date , int year){
        Calendar calendar = Calendar.getInstance();
        if (date != null){
            calendar.setTime(date);
        }
        calendar.add(Calendar.YEAR,year);
        return calendar.getTime();
    }

    /**
     *判断两个HH:mm相差多少分钟
     * @param startTime
     * @param endTime
     * @return
     */
    public static Long getMinute(String startTime, String endTime){
        try {
            Date parse = getSdf(HH_MM).parse(startTime);
            Date parse1 = getSdf(HH_MM).parse(endTime);
            GregorianCalendar calendar1 = new GregorianCalendar();
            GregorianCalendar calendar2 = new GregorianCalendar();
            calendar1.setTime(parse);
            calendar2.setTime(parse1);
            return (calendar2.getTimeInMillis() - calendar1.getTimeInMillis()) / (1000 * 60);
        } catch (ParseException e) {
            return 0L;
        }
    }
    /**
     * 获取HH:mm，n分钟之后的时间 HH:mm
     */
    public static String getEndTime(String startTime, Integer n) {
        try {
            Date start = getSdf(HH_MM).parse(startTime);
            GregorianCalendar calendar1 = new GregorianCalendar();
            calendar1.setTime(start);
            calendar1.setTimeInMillis(calendar1.getTimeInMillis() + n * 60 * 1000);
            return new SimpleDateFormat(HH_MM).format(calendar1.getTime());
        } catch (Exception e) {
            return null;
        }
    }
    /**
     * 判断时间是否在两个HH:mm时间之间（minute时间偏移）
     */
    public static Boolean checkTime(String startTime, String endTime, Integer minute) {
        try {
            String today = getYyyy_MM_ddByToday() + " ";
            Date start = StringToDate1(today + startTime);
            Date end = StringToDate1(today + endTime);
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MINUTE, minute);
            Date date = calendar.getTime();
            if (start.getTime() < date.getTime() && date.getTime() <= end.getTime()) {
                return true;
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    /**
     * 判断两个HH:mm大小，时间1大于等于时间2，则返回true
     */
    public static Boolean compareTime(String time1, String time2) {
        try {
            String today = getYyyy_MM_ddByToday() + " ";
            Date date1 = StringToDate1(today + time1);
            Date date2 = StringToDate1(today + time2);
            if (date1.getTime() >= date2.getTime()) {
                return true;
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    /**
     * 获取指定格式的日期
     * @param parse
     * @return
     */
    public static Date StringToDate1(String parse){
        try {
            return getSdf(yyyy_MM_dd).parse(parse);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 返回指定日期后n天
     * @return
     */
    public static List<String> rangeOffsetDay(Date date,int day){
       List<String> list = new ArrayList<>();
        for (int i = 1; i < day; i++) {
            Date offsetDay = offsetDay(date, -i);
            list.add(cn.hutool.core.date.DateUtil.format(offsetDay,"yyyy-MM-dd"));
        }
        return list;
    }

    /**
     * 获取偏移时间：以时为准
     * @param date
     * @param offsetHour
     * @return
     */
    public static Date offsetHour(Date date,int offsetHour){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR,offsetHour);
        return calendar.getTime();
    }
    public static void main(String[] args) {
        Date date = offsetDay(new Date(), -1);
        System.out.println(getFormatDate(offsetHour(new Date(),-1),yyyyMMdd_HHmmss));
    }

}
